package vip.geeker.iotms.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.catalina.manager.util.SessionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.geeker.iotms.dto.DeviceInfoDto;
import vip.geeker.iotms.dto.DeviceTypeDto;
import vip.geeker.iotms.dto.UserDto;
import vip.geeker.iotms.dto.WarnRuleDto;
import vip.geeker.iotms.help.Constants;
import vip.geeker.iotms.help.Response;
import vip.geeker.iotms.persistance.mapper.DeviceInfoMapper;
import vip.geeker.iotms.persistance.mapper.DeviceWarnInfoMapper;
import vip.geeker.iotms.persistance.model.*;
import vip.geeker.iotms.service.*;
import vip.geeker.iotms.utils.ObjectUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * redis对象序列化工具
 *
 * @author zhoup
 * @create 2020-04-2711:23:00
 * @Email acacio@foxmail.com
 * To change this template use File | Settings | Editor | File and Code Templates.
 **/
@Service
@Transactional(readOnly = false)
public class DeviceService extends ServiceImpl<DeviceInfoMapper, DeviceInfo> implements IDeviceService {
    @Resource
    private IDeviceTypeService deviceTypeService;

    @Resource
    private DeviceParamsService deviceParamsService;

    @Resource
    private DeviceInfoMapper deviceInfoMapper;

    @Resource
    private IDeviceDataService deviceDataService;

    @Resource
    private IDeviceTypeDataService deviceTypeDataService;

    @Resource
    private DataSplitRuleService dataSplitRuleService;

    @Resource
    private WarnRuleService warnRuleService;

    @Resource
    private DeviceWarnInfoMapper warnInfoMapper;

//    @Resource
//    private DeviceTypeDataMapper deviceTypeDataMapper;

    public List<DeviceType> queryDeviceTypeList(DeviceType type) {
        return deviceTypeService.queryDeviceTypeList(type);
    }

    public PageInfo<DeviceType> queryPage(DeviceType type) {
        return deviceTypeService.queryPage(type);
    }

    public PageInfo<DeviceInfo> queryPage(DeviceInfo info) {
        PageHelper.startPage(info.getPageNo(), info.getPageSz());
        List<DeviceInfo> list = deviceInfoMapper.queryList(info);
        return new PageInfo<>(list);
    }

    @Override
    public DeviceInfo selectDeviceInfoByPrimaryKey(Integer id) {
        return deviceInfoMapper.selectByPrimaryKey(id);
    }

    @Transactional(readOnly = false)
    @Override
    public Boolean updateByPrimaryKeySelective(DeviceInfo info) {
        return deviceInfoMapper.updateByPrimaryKeySelective(info) > 0;
    }

    @Transactional(readOnly = false)
    @Override
    public Boolean addDeviceInfo(DeviceInfo record) {
        record.setId(deviceInfoMapper.nextVal());
        return deviceInfoMapper.insertSelective(record) > 0;
    }

    public Response<DeviceTypeData> selectDeviceTypeDataByTypeId(Integer id) {
        return deviceTypeDataService.selectById(id);
    }

    @Transactional(readOnly = false)
    public Response insertDeviceTypeDataSelective(DeviceTypeData record) {
        return deviceTypeDataService.addDeviceTypeData(record);
    }

    public Response updateDeviceTypeDataByPrimaryKeySelective(DeviceTypeData record) {
        return deviceTypeDataService.updateDeviceTypeData(record);
    }

    public Response queryPage(DeviceTypeData data) {
        return deviceTypeDataService.queryPage(data);
    }

    public PageInfo<DeviceParams> queryPage(DeviceParams params) {
        return deviceParamsService.queryPage(params);
    }

    @Transactional(readOnly = false)
    public Response addDeviceType(DeviceType type) {
        return deviceTypeService.addDeviceType(type);
    }

    public List<DeviceTypeDto> queryDeviceTypeTree(DeviceTypeDto deviceTypeDto) {
        return deviceTypeService.queryDeviceTypeTree(deviceTypeDto);
    }

    public DeviceType selectDeviceTypeByPrimaryKey(Integer id) {
        return deviceTypeService.selectByPrimaryKey(id);
    }

    @Transactional(readOnly = false)
    public boolean updateByPrimaryKeySelective(DeviceType deviceType) {
        return deviceTypeService.updateByPrimaryKeySelective(deviceType) > 0 ? true : false;
    }

    @Transactional(readOnly = false)
    public Response addDeviceParams(DeviceParams params) {
        return deviceParamsService.addDeviceParams(params);
    }

    @Transactional(readOnly = false)
    public boolean updateByPrimaryKeySelective(DeviceParams params) {
        return deviceParamsService.updateByPrimaryKeySelective(params) > 0 ? true : false;
    }


    public DeviceParams selectDeviceParamsByPrimaryKey(Integer id) {
        return deviceParamsService.selectByPrimaryKey(id);
    }


    public Response<PageInfo> queryDataPage(DeviceData data) {
        return deviceDataService.queryPage(data);
    }

    public Response<PageInfo> queryDataSplitRulePage(DataSplitRule dataSplitRule) {
        return dataSplitRuleService.queryPageInfoList(dataSplitRule);
    }

    public Boolean addRuleSplitRule(DataSplitRule dataSplitRule) {
        if(ObjectUtils.isNotNullAndEmpty(dataSplitRule.getId())){
            dataSplitRule.setLastUpdTime(new Date());
            return dataSplitRuleService.updateByPrimaryKeySelective(dataSplitRule);
        }
        dataSplitRule.setCreateTime(new Date());
        dataSplitRule.setDeleteFlag(false);
        return dataSplitRuleService.addRuleSplitRule(dataSplitRule);
    }

    public Boolean toDeleteSplitRule(DataSplitRule dataSplitRule) {
        dataSplitRule.setLastUpdTime(new Date());
        dataSplitRule.setDeleteFlag(true);
        return dataSplitRuleService.updateByPrimaryKeySelective(dataSplitRule);
    }

    public DataSplitRule queryById(Integer id) {
        return dataSplitRuleService.queryById(id);
    }

    @Override
    @Transactional
    public void analysisData(Integer deviceId, String redisValue) {
        // 1.从redis 中获取数据
        String redisData = redisValue;
        // 2.根据设备编号获取设备类型，获取设备的解析规则,解析数据
        List<DeviceInfoDto> list = deviceInfoMapper.queryAnalysisRule(deviceId.toString());
        if(ObjectUtils.isNotNullAndEmpty(list)){
            DeviceInfoDto deviceInfoDto = list.get(0);
            HashMap<String, String> map = new HashMap<>();
            for (DeviceInfoDto dto:list) {
                map.put(dto.getSort(),dto.getTypeDataId());
            }
            deviceInfoDto.setMap(map);
            String[] split = redisData.split("\\".concat(deviceInfoDto.getSeperator()) );
            List<DeviceData> deviceDatas = new ArrayList<>();
            Map<Integer, BigDecimal> deviceDataMap = new HashMap<>();
            for (int i = 0; i <split.length ; i++) {
                DeviceData deviceData = new DeviceData();
                deviceData.setParamsId(Integer.valueOf(map.get(String.valueOf(i))));
                deviceData.setParamsValue(new BigDecimal(split[i]));
                deviceData.setCreateTime(new Date());
                deviceData.setDeviceId(deviceId);
                deviceDatas.add(deviceData);
                deviceDataMap.put(Integer.valueOf(map.get(String.valueOf(i))),new BigDecimal(split[i]));

            }
            // 3.将数据存入设备数据表device_param
            deviceDataService.insertByBatch(deviceDatas);
            // 4.匹配告警规则,生成告警数据插入device_warn_info 表
            // 获取告警规则
            WarnRule warnRule = new WarnRule();
            warnRule.setDeviceType(deviceInfoDto.getTypeId());
            List<WarnRuleDto> warnRuleDtos = warnRuleService.queryList(warnRule);
            if(ObjectUtils.isNotNullAndEmpty(warnRuleDtos)){
                // 匹配告警规则，生成告警信息
                for (WarnRuleDto dto:warnRuleDtos) {
                    BigDecimal bigDecimal = deviceDataMap.get(dto.getParamsId());
                    if (bigDecimal.compareTo(dto.getMinValue()) == -1){
                        // 生成异常数据
                        generaterWarnInfoData(deviceId,bigDecimal,dto.getId());
                    }else if(bigDecimal.compareTo(dto.getMaxValue()) == 1){
                        // 生成异常数据
                        generaterWarnInfoData(deviceId,bigDecimal,dto.getId());
                    }
                }
            }
        }


    }

    private DeviceWarnInfo generaterWarnInfoData(Integer deviceId ,BigDecimal warnValue,Integer ruleId){
        DeviceWarnInfo deviceWarnInfo = new DeviceWarnInfo();
        deviceWarnInfo.setDeviceId(deviceId);
        deviceWarnInfo.setHitRuleId(ruleId);
        deviceWarnInfo.setWarnValue(warnValue);
        warnInfoMapper.insertSelective(deviceWarnInfo);
        return deviceWarnInfo;
    }
}
